/**
 * Copyright (c) 2010 BullionXpress.com,
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */


package com.bullionxpress.shared.model;

import java.io.Serializable;
import java.util.Date;
import java.sql.Timestamp;
import java.util.Calendar;

import com.bullionxpress.shared.model.Account;
import com.bullionxpress.shared.util.Utility;

/**
 *
 * @author BullionXpress.com
 */
public abstract class Order implements Serializable {
    private Account account = null;
    private OrderType orderType = null;
    private StopLossOrder stopLoss = null;
    private TakeProfitOrder takeProfit = null;
    private Instrument instrument = null;
    private String transactionId;
    private String id;
    private long units;
    private long quantityFilled;
    private double price;
    private Date expiry;
    private OrderStatus status = OrderStatus.OPEN;
    static long m = 0;
    public static int NOT_SET = -1;

    protected Order()
    {
        id = "O" + Long.toHexString(Utility.generateId());
        transactionId = null;
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_YEAR, 1);
        expiry = c.getTime();
    }

    

    public boolean isFilled()
    {
        return ( status == OrderStatus.FILLED ) ;
    }
    public boolean isRejected()
    {
        return ( status == OrderStatus.REJECTED ) ;
    }

    public boolean isLocked()
    {
        return ( status == OrderStatus.LOCKED ) ;
    }

    public boolean isClosed()
    {
        return ( status == OrderStatus.CLOSED ) ;
    }

    public boolean isOpen()
    {
        return ( status == OrderStatus.OPEN );
    }

    public boolean isExpired()
    {
        try {
            boolean retVal = false;
            Calendar c = Calendar.getInstance();
            c.setTime(new Date(System.currentTimeMillis()));
            Calendar when = Calendar.getInstance();
            when.setTime(expiry);
            if( c.after(when)){
                retVal = true;
            }
            return retVal;
        } catch(Exception ex){
            ex.printStackTrace();
            return false;
        }
    }

    public boolean isSellOrder()
    {
        return ( orderType == OrderType.SELL );
    }

    public boolean isBuyOrder()
    {
        return ( orderType == OrderType.BUY );
    }

    /**
     * @return the stopLoss
     */
    public StopLossOrder getStopLoss() {
        return stopLoss;
    }

    /**
     * @param stopLoss the stopLoss to set
     */
    public void setStopLoss(StopLossOrder stopLoss) {
        this.stopLoss = stopLoss;
    }

    /**
     * @return the takeProfit
     */
    public TakeProfitOrder getTakeProfit() {
        return takeProfit;
    }

    /**
     * @param takeProfit the takeProfit to set
     */
    public void setTakeProfit(TakeProfitOrder takeProfit) {
        this.takeProfit = takeProfit;
    }

    /**
     * @return the transactionId
     */
    public String getTransactionId() {
        return transactionId;
    }

    /**
     * @param transactionId the transactionId to set
     */
    public void setTransactionId(String transactionId) {
        this.transactionId = transactionId;
    }

    /**
     * @return the units
     */
    public long getUnits() {
        return units;
    }

    /**
     * @param units the units to set
     */
    public void setUnits(long units) {
        this.units = units;
    }

    /**
     * @return the price
     */
    public double getPrice() {
        return price;
    }

    /**
     * @param price the price to set
     */
    public void setPrice(double price) {
        this.price = price;
    }

    /**
     * @return the expiry
     */
    public Date getExpiry() {
        return expiry;
    }

    /**
     * @param expiry the expiry to set
     */
    public void setExpiry(Date expiry) {
        this.expiry = expiry;
    }

    /**
     * @return the orderType
     */
    public OrderType getOrderType() {
        return orderType;
    }

    /**
     * @param orderType the orderType to set
     */
    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }

    /**
     * @return the account
     */
    public Account getAccount() {
        return account;
    }

    /**
     * @param account the account to set
     */
    public void setAccount(Account account) {
        this.account = account;
    }

    /**
     * @return the status
     */
    public OrderStatus getStatus() {
        return status;
    }

    /**
     * @param status the status to set
     */
    public void setStatus(OrderStatus status) {
        this.status = status;
    }

    /**
     * @return the quantityFilled
     */
    public long getQuantityFilled() {
        return quantityFilled;
    }

    public long getRemainingUnits()
    {
        return ( units - quantityFilled );
    }

    /**
     * @param quantityFilled the quantityFilled to set
     */
    public void addQuantityFilled(long qf) {
        if( ( this.quantityFilled + qf ) > units ){
            throw new IllegalArgumentException("You cannot fill more than the units available");
        }
        this.quantityFilled += qf;
    }

    /**
     * @return the orderId
     */
    public String getId() {
        return id;
    }

    /**
     * @param orderId the orderId to set
     */
    public void setId(String orderId) {
        this.id = orderId;
    }

    public String toString()
    {
        String side = "";
        if( isBuyOrder() ){
            side = "buy";
        } else if( isSellOrder() ){
            side = "sell";
        }
        return id + " qf:" + quantityFilled + " ru:" + getRemainingUnits() + " p:" + price + " u:" + units + " " + side + " " + status + " " + instrument;
    }



    /**
     * @return the instrument
     */
    public Instrument getInstrument() {
        return instrument;
    }

    /**
     * @param instrument the instrument to set
     */
    public void setInstrument(Instrument instrument) {
        this.instrument = instrument;
    }
}
